﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Spatial.Metadata;
using NHibernate.Spatial.Mapping;
using NHibernate.Linq;

namespace Persistencia.NHibernate
{
    public class NHibernatePersistencia : MarshalByRefObject, IRepositorio
    {
        #region Atributos

        /// <summary>
        /// Session
        /// </summary>
        private ISession miSession;

        /// <summary>
        /// Session Factory
        /// </summary>
        private ISessionFactory miSessionFactory;
        private Configuration miConfiguration = new Configuration();
        

        private static IRepositorio Repositorio;

        #endregion

        #region Constructor

        private NHibernatePersistencia()
        {
            //miConfiguration.Configure("hibernate.cfg.xml");
            try
            {
                miConfiguration.Configure();
                miConfiguration.AddAuxiliaryDatabaseObject(new SpatialAuxiliaryDatabaseObject(miConfiguration));
                //Metadata.AddMapping(miConfiguration, MetadataClass.GeometryColumn);
                //Metadata.AddMapping(miConfiguration, MetadataClass.SpatialReferenceSystem);
                this.miSessionFactory = miConfiguration.BuildSessionFactory();
                this.miSession = this.SessionFactory.OpenSession();               

            }
            catch (Exception ex)
            {
                
                throw ex;
            }

        }

        public static IRepositorio Instancia
        {
            get
            {
                if (Repositorio == null)
                {
                    Repositorio = new NHibernatePersistencia();
                }
                return Repositorio;
            }
        }

        #endregion

        #region Propiedades

        /// <summary>
        /// Sesion de NHibernate
        /// </summary>
        public ISession Session
        {
            get { return miSession.SessionFactory.GetCurrentSession(); }
        }

        /// <summary>
        /// Sesion de NHibernate
        /// </summary>
        public ISessionFactory SessionFactory
        {
            get { return this.miSessionFactory; }
        }

        #endregion

        #region Metodos

        public T Obtener<T>(object Id)
        {
            if (!Session.IsConnected)
            {
                Session.Reconnect();
            }
            this.Session.Flush();
            return this.Session.Load<T>(Id);
        }

        public void Persistir<T>(T entidad)
        {
            this.Session.Save(entidad);
        }

        public void Actualizar<T>(T entidad)
        {
            this.Session.SaveOrUpdate(entidad);
        }

        public void Eliminar<T>(T entidad)
        {
            this.Session.Delete(entidad);
        }

        public IQueryable<T> Listar<T>()
        {
            if (!Session.IsConnected)
            {
                Session.Reconnect();
            }
            this.Session.Flush();
            return this.Session.Linq<T>();            
        }

      

        #endregion

        #region IRepositorio Members

        public void IniciarTransaccion()
        {
            if (!this.Session.IsConnected)
            {
                this.Session.Reconnect();
            }
            this.Session.BeginTransaction();
        }

        public void AceptarTransaccion()
        {
            this.Session.Flush();
            this.Session.Transaction.Commit();
            if (this.Session.IsConnected)
            {
                this.Session.Disconnect();
            }
        }

        public void CancelarTransaccion()
        {
            this.Session.Transaction.Rollback();
            if (this.Session.IsConnected)
            {
                this.Session.Disconnect();
            }
        }

        public void LimpiarSesion()
        {
            this.Session.Flush();
        }

       
        #endregion
    }
}
